// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.network;

import java.nio.ByteBuffer;
import java.util.HashSet;
import zombie.core.network.ByteBufferWriter;
import zombie.core.raknet.UdpConnection;
import zombie.debug.DebugLog;
import zombie.debug.LogSeverity;

public class ItemTransactionManager {
    private static final HashSet<ItemTransactionManager.ItemRequest> requests = new HashSet();

    public static void update() {
        requests.removeIf(ItemTransactionManager.ItemRequest::isTimeout);
    }

    public static boolean isConsistent(int itemID, int srcID, int dstID) {
        return requests.stream()
            .filter(
                itemRequest -> itemID == itemRequest.itemID
                        || srcID == itemRequest.itemID
                        || dstID == itemRequest.itemID
                        || itemID == itemRequest.srcID
                        || itemID == itemRequest.dstID
            )
            .noneMatch(itemRequest -> itemRequest.state == 1);
    }

    public static void receiveOnClient(ByteBuffer bb, short packetType) {
        try {
            byte _byte = bb.get();
            int int0 = bb.getInt();
            int int1 = bb.getInt();
            int int2 = bb.getInt();
            DebugLog.Multiplayer.debugln("%d [ %d : %d => %d ]", _byte, int0, int1, int2);
            requests.stream()
                .filter(itemRequest -> int0 == itemRequest.itemID && int1 == itemRequest.srcID && int2 == itemRequest.dstID)
                .forEach(itemRequest -> itemRequest.setState(_byte));
        } catch (Exception exception) {
            DebugLog.Multiplayer.printException(exception, "ReceiveOnClient: failed", LogSeverity.Error);
        }
    }

    public static void receiveOnServer(ByteBuffer bb, UdpConnection connection, short packetType) {
        try {
            byte _byte = bb.get();
            int int0 = bb.getInt();
            int int1 = bb.getInt();
            int int2 = bb.getInt();
            if (0 == _byte) {
                if (isConsistent(int0, int1, int2)) {
                    requests.add(new ItemTransactionManager.ItemRequest(int0, int1, int2));
                    sendItemTransaction(connection, (byte)2, int0, int1, int2);
                    DebugLog.Multiplayer.trace("set accepted [ %d : %d => %d ]", int0, int1, int2);
                } else {
                    sendItemTransaction(connection, (byte)1, int0, int1, int2);
                    DebugLog.Multiplayer.trace("set rejected [ %d : %d => %d ]", int0, int1, int2);
                }
            } else {
                requests.removeIf(itemRequest -> int0 == itemRequest.itemID && int1 == itemRequest.srcID && int2 == itemRequest.dstID);
                DebugLog.Multiplayer.trace("remove processed [ %d : %d => %d ]", int0, int1, int2);
            }
        } catch (Exception exception) {
            DebugLog.Multiplayer.printException(exception, "ReceiveOnClient: failed", LogSeverity.Error);
        }
    }

    public static void createItemTransaction(int itemID, int srcID, int dstID) {
        if (isConsistent(itemID, srcID, dstID)) {
            requests.add(new ItemTransactionManager.ItemRequest(itemID, srcID, dstID));
            sendItemTransaction(GameClient.connection, (byte)0, itemID, srcID, dstID);
        }
    }

    public static void removeItemTransaction(int itemID, int srcID, int dstID) {
        if (requests.removeIf(itemRequest -> int0 == itemRequest.itemID && int1 == itemRequest.srcID && int2 == itemRequest.dstID)) {
            sendItemTransaction(GameClient.connection, (byte)2, itemID, srcID, dstID);
        }
    }

    private static void sendItemTransaction(UdpConnection udpConnection, byte _byte, int int0, int int1, int int2) {
        if (udpConnection != null) {
            ByteBufferWriter byteBufferWriter = udpConnection.startPacket();

            try {
                PacketTypes.PacketType.ItemTransaction.doPacket(byteBufferWriter);
                byteBufferWriter.putByte(_byte);
                byteBufferWriter.putInt(int0);
                byteBufferWriter.putInt(int1);
                byteBufferWriter.putInt(int2);
                PacketTypes.PacketType.ItemTransaction.send(udpConnection);
            } catch (Exception exception) {
                udpConnection.cancelPacket();
                DebugLog.Multiplayer.printException(exception, "SendItemTransaction: failed", LogSeverity.Error);
            }
        }
    }

    private static class ItemRequest {
        private static final byte StateUnknown = 0;
        private static final byte StateRejected = 1;
        private static final byte StateAccepted = 2;
        private final int itemID;
        private final int srcID;
        private final int dstID;
        private final long timestamp;
        private byte state;

        private ItemRequest(int int0, int int1, int int2) {
            this.itemID = int0;
            this.srcID = int1;
            this.dstID = int2;
            this.timestamp = zombie.GameTime.getServerTimeMills() + 5000L;
            this.state = (byte)(GameServer.bServer ? 1 : 0);
        }

        private void setState(byte _byte) {
            this.state = _byte;
        }

        private boolean isTimeout() {
            return zombie.GameTime.getServerTimeMills() > this.timestamp;
        }
    }
}
